'Copyright 2006 James Downey

Imports System.Xml

Public Class Filter

    '  <!--
    '  filter element - used for constructing complex conditionals
    '           legal one entity and linked-entity
    '-->
    '<ElementType name='filter' content='eltOnly' model='closed'>
    '  <AttributeType name='type' dt:type='enumeration' 
    '                 dt:values='and or' required='no' default='and' />
    '  <!-- -->

    '  <attribute type='type' />
    '  <element type='condition' minOccurs='0' maxOccurs='*' />
    '  <element type='filter' minOccurs='0' maxOccurs='*' />
    '</ElementType>
    '<!--

    Public Type As FilterType = FilterType.TypeAnd
    Private mConditions As Conditions
    Private mFilters As Filters

    Public Sub New()
        mConditions = New Conditions()
        mFilters = New Filters()
    End Sub

    Public Sub New(ByVal FilterNode As XmlNode)
        Me.New()
        If Not FilterNode.Attributes("type") Is Nothing Then
            If FilterNode.Attributes("type").Value = "or" Then
                Me.Type = FilterType.TypeOR
            End If
        End If
        Dim conditionnode As XmlNode
        Dim conditionnodes As XmlNodeList
        conditionnodes = FilterNode.SelectNodes("./condition")
        For Each conditionnode In conditionnodes
            Me.Conditions.Add(New Condition(conditionnode))
        Next
        Dim subfilternode As XmlNode
        Dim filternodes As XmlNodeList
        filternodes = filternode.selectnodes("./filter")
        For Each subfilternode In filternodes
            Me.Filters.Add(New Filter(subfilternode))
        Next
    End Sub

    Public ReadOnly Property Conditions() As Conditions
        Get
            Return mConditions
        End Get
    End Property

    Public ReadOnly Property Filters() As Filters
        Get
            Return mFilters
        End Get
    End Property

    Public Overrides Function ToString() As String
        Dim strFilter As String = ""
        Dim condition As Condition
        For Each condition In Me.Conditions
            If strFilter.Length > 0 Then
                If Me.Type = FilterType.TypeAnd Then
                    strFilter &= " and "
                Else
                    strFilter &= " or "
                End If
            End If
            strFilter &= condition.ToString
        Next
        If Not strFilter.Length = 0 Then strFilter &= " "
        If Me.Filters.Count > 0 Then
            If Me.Type = FilterType.TypeAnd Then
                strFilter &= "and (" & SubFiltersToString() & ") "
            Else
                strFilter &= "or (" & SubFiltersToString() & ") "
            End If
        End If
        Return strFilter
    End Function

    private function SubFiltersToString() as string
        Dim f As Filter
        Dim strFilter As String = ""
        For Each f In Me.Filters
            strFilter &= "(" & f.ToString & ")"
        Next
        Return strFilter
    End Function



    Public Function ToXML() As String
        Dim strXML As String
        strXML = "<filter type='"
        If Me.Type = FilterType.TypeAnd Then
            strXML &= "and'>"
        Else
            strXML &= "or'>"
        End If
        Dim filter As Filter
        For Each filter In Filters
            strXML &= filter.ToXML
        Next
        Dim condition As Condition
        For Each condition In Me.Conditions
            strXML &= condition.ToXML
        Next
        strXML &= "</filter>"
        Return strXML
    End Function

End Class

Public Enum FilterType
    TypeAnd
    TypeOR
End Enum
